# Tab Layout

## Examples


### Uncontrolled

```typescript
import React from 'react';

import P from '@splunk/react-ui/Paragraph';
import TabLayout from '@splunk/react-ui/TabLayout';


function Uncontrolled() {
    return (
        <TabLayout defaultActivePanelId="platform">
            <TabLayout.Panel label="Platform" panelId="platform">
                <P>
                    The extensible data platform powers unified security, full-stack observability
                    and limitless custom applications.
                </P>
            </TabLayout.Panel>
            <TabLayout.Panel label="Security" panelId="security">
                <P>
                    Protect your business and modernize your security operations with a
                    best-in-class data platform, advanced analytics and automated investigations and
                    response.
                </P>
            </TabLayout.Panel>
            <TabLayout.Panel label="Observability" panelId="observability">
                <P>
                    Solve problems in seconds with the only full-stack, analytics-powered and
                    OpenTelemetry-native observability solution.
                </P>
            </TabLayout.Panel>
        </TabLayout>
    );
}

export default Uncontrolled;
```



### Controlled

In this example, the open Panel is controlled by the parent component.

```typescript
import React, { useState } from 'react';

import P from '@splunk/react-ui/Paragraph';
import TabLayout, { TabLayoutChangeHandler } from '@splunk/react-ui/TabLayout';


function Controlled() {
    const [activePanelId, setActivePanelId] = useState<string | undefined>('platform');

    const handleChange: TabLayoutChangeHandler = (e, { activePanelId: panelId }) => {
        setActivePanelId(panelId);
    };

    return (
        <TabLayout activePanelId={activePanelId} onChange={handleChange}>
            <TabLayout.Panel label="Platform" panelId="platform">
                <P>
                    The extensible data platform powers unified security, full-stack observability
                    and limitless custom applications.
                </P>
            </TabLayout.Panel>
            <TabLayout.Panel label="Security" panelId="security">
                <P>
                    Protect your business and modernize your security operations with a
                    best-in-class data platform, advanced analytics and automated investigations and
                    response.
                </P>
            </TabLayout.Panel>
            <TabLayout.Panel label="Observability" panelId="observability">
                <P>
                    Solve problems in seconds with the only full-stack, analytics-powered and
                    OpenTelemetry-native observability solution.
                </P>
            </TabLayout.Panel>
        </TabLayout>
    );
}

export default Controlled;
```



### Auto activate

In this example, switching to a tab with the keyboard automatically activates it.

```typescript
import React from 'react';

import P from '@splunk/react-ui/Paragraph';
import TabLayout from '@splunk/react-ui/TabLayout';


function AutoActivate() {
    return (
        <TabLayout autoActivate defaultActivePanelId="platform">
            <TabLayout.Panel label="Platform" panelId="platform">
                <P>
                    The extensible data platform powers unified security, full-stack observability
                    and limitless custom applications.
                </P>
            </TabLayout.Panel>
            <TabLayout.Panel label="Security" panelId="security">
                <P>
                    Protect your business and modernize your security operations with a
                    best-in-class data platform, advanced analytics and automated investigations and
                    response.
                </P>
            </TabLayout.Panel>
            <TabLayout.Panel label="Observability" panelId="observability">
                <P>
                    Solve problems in seconds with the only full-stack, analytics-powered and
                    OpenTelemetry-native observability solution.
                </P>
            </TabLayout.Panel>
        </TabLayout>
    );
}

export default AutoActivate;
```



### Icons

```typescript
import React from 'react';

import ChartBarIcon from '@splunk/react-icons/ChartBar';
import SearchIcon from '@splunk/react-icons/Magnifier';
import TableIcon from '@splunk/react-icons/Table';
import Heading from '@splunk/react-ui/Heading';
import Paragraph from '@splunk/react-ui/Paragraph';
import Prose from '@splunk/react-ui/Prose';
import TabLayout from '@splunk/react-ui/TabLayout';


function Icons() {
    return (
        <TabLayout defaultActivePanelId="search">
            <TabLayout.Panel label="Search" panelId="search" icon={<SearchIcon />}>
                <Prose>
                    <Heading level={4}>Search</Heading>
                    <Paragraph>
                        There are six broad types for all of the search commands: distributable
                        streaming, centralized streaming, transforming, generating, orchestrating
                        and dataset processing.
                    </Paragraph>
                </Prose>
            </TabLayout.Panel>
            <TabLayout.Panel label="Statistics" panelId="statistics" icon={<TableIcon />}>
                <Prose>
                    <Heading level={4}>Statistics</Heading>
                    <Paragraph>
                        You can use the statistical and charting functions with the chart, stats,
                        and timechart commands.
                    </Paragraph>
                </Prose>
            </TabLayout.Panel>
            <TabLayout.Panel
                label="Visualizations"
                panelId="visualizations"
                icon={<ChartBarIcon />}
            >
                <Prose>
                    <Heading level={4}>Visualizations</Heading>
                    <Paragraph>
                        There are many different types of visualizations available, including line
                        charts, area charts, and bar charts to name a few.
                    </Paragraph>
                </Prose>
            </TabLayout.Panel>
        </TabLayout>
    );
}

export default Icons;
```



### Vertical

```typescript
import React from 'react';

import Heading from '@splunk/react-ui/Heading';
import Paragraph from '@splunk/react-ui/Paragraph';
import Prose from '@splunk/react-ui/Prose';
import TabLayout from '@splunk/react-ui/TabLayout';


function Vertical() {
    return (
        <TabLayout defaultActivePanelId="platform" layout="vertical">
            <TabLayout.Panel label="Platform" panelId="platform">
                <Prose>
                    <Heading level={4}>Platform</Heading>
                    <Paragraph>
                        The extensible data platform powers unified security, full-stack
                        observability and limitless custom applications.
                    </Paragraph>
                </Prose>
            </TabLayout.Panel>
            <TabLayout.Panel label="Security" panelId="security">
                <Prose>
                    <Heading level={4}>Security</Heading>
                    <Paragraph>
                        Protect your business and modernize your security operations with a
                        best-in-class data platform, advanced analytics and automated investigations
                        and response.
                    </Paragraph>
                </Prose>
            </TabLayout.Panel>
            <TabLayout.Panel label="Observability" panelId="observability">
                <Prose>
                    <Heading level={4}>Observability</Heading>
                    <Paragraph>
                        Solve problems in seconds with the only full-stack, analytics-powered and
                        OpenTelemetry-native observability solution.
                    </Paragraph>
                </Prose>
            </TabLayout.Panel>
        </TabLayout>
    );
}

export default Vertical;
```



### Vertical Icons

```typescript
import React from 'react';

import ChartBarIcon from '@splunk/react-icons/ChartBar';
import SearchIcon from '@splunk/react-icons/Magnifier';
import TableIcon from '@splunk/react-icons/Table';
import Heading from '@splunk/react-ui/Heading';
import Paragraph from '@splunk/react-ui/Paragraph';
import Prose from '@splunk/react-ui/Prose';
import TabLayout from '@splunk/react-ui/TabLayout';


function VerticalIcons() {
    return (
        <TabLayout defaultActivePanelId="search" layout="vertical">
            <TabLayout.Panel label="Search" panelId="search" icon={<SearchIcon />}>
                <Prose>
                    <Heading level={4}>Search</Heading>
                    <Paragraph>
                        There are six broad types for all of the search commands: distributable
                        streaming, centralized streaming, transforming, generating, orchestrating
                        and dataset processing.
                    </Paragraph>
                </Prose>
            </TabLayout.Panel>
            <TabLayout.Panel label="Statistics" panelId="statistics" icon={<TableIcon />}>
                <Prose>
                    <Heading level={4}>Statistics</Heading>
                    <Paragraph>
                        You can use the statistical and charting functions with the chart, stats,
                        and timechart commands.
                    </Paragraph>
                </Prose>
            </TabLayout.Panel>
            <TabLayout.Panel
                label="Visualizations"
                panelId="visualizations"
                icon={<ChartBarIcon />}
            >
                <Prose>
                    <Heading level={4}>Visualizations</Heading>
                    <Paragraph>
                        There are many different types of visualizations available, including line
                        charts, area charts, and bar charts to name a few.
                    </Paragraph>
                </Prose>
            </TabLayout.Panel>
        </TabLayout>
    );
}

export default VerticalIcons;
```




## API


### TabLayout API

The `TabLayout` is a group of managed `Panels`. Only one panel can be open at a time.
`TabLayout` supports both the controlled and uncontrolled patterns.

#### Props

| Name | Type | Required | Default | Description |
|------|------|------|------|------|
| activePanelId | string | no |  | The `panelId` of the `TabLayout.Panel` to activate. If set, an `onChange` callback is required. |
| autoActivate | boolean | no |  | If `true`, tabs will trigger the `onChange` callback when they receive focus. |
| children | React.ReactNode | no |  | Must be `TabLayout.Panel`. |
| defaultActivePanelId | string | no |  | Sets the active panel on the initial render. It must match the `panelId` of one of the child `TabLayout.Panel`s. Only use `defaultActivePanelId` when using `TabLayout` as an uncontrolled component. |
| elementRef | React.Ref<HTMLDivElement> | no |  | A React ref which is set to the DOM element when the component mounts and null when it unmounts. |
| iconPosition | 'above' \| 'left' | no |  | **DEPRECATED**: This prop is deprecated and will be removed in the next major version. Position of icon in `TabBar.Tab` if it has an icon. Defaults to "left". |
| layout | 'horizontal' \| 'vertical' | no | 'horizontal' | The layout direction for tabs. |
| maxTabWidth | number | no |  | Max width of each `TabBar.Tab` in pixels. Leave blank for auto max width. |
| onChange | TabLayoutChangeHandler | no |  | A callback that receives the event and data (`selectedPanelId`). If activePanelId is set, this callback is required. |

#### Types

| Name | Type | Description |
|------|------|------|
| TabLayoutChangeHandler | (     event: React.MouseEvent<HTMLButtonElement> \| React.FocusEvent<HTMLButtonElement>,     data: { activePanelId?: string } ) => void |  |



### TabLayout.Panel API

#### Props

| Name | Type | Required | Default | Description |
|------|------|------|------|------|
| children | React.ReactNode | no |  |  |
| count | number | no |  | Inserts number in tab label. |
| disabled | boolean | no | false | Prevents user from clicking the tab. |
| elementRef | React.Ref<HTMLDivElement> | no |  | A React ref which is set to the DOM element when the component mounts and null when it unmounts. |
| icon | React.ReactNode | no |  | See Icon documentation for more information. |
| inset | boolean | no | true | By default, adds padding to panel content. If set to false, renders panel content without padding. |
| label | React.ReactNode | no |  | The text shown in the button. |
| panelId | string | yes |  | A unique `id` for this panel and used by the `TabLayout` to keep track of the open panel. |
| tooltip | React.ReactNode | no |  | Content to show in a tooltip when the user hovers over or focuses on the tab.  Note: The tooltip will override the label for the Panel for screen readers. |





## Accessibility

> NOT suported by design system: tab list overflow, configurable (add, delete, reorder) tab lists

## Visual Design
- Color contrast ratio **MUST** be:
    - &gt= 4.5:1 for normal text: 14 pt (typically 18.66px) and bold or larger [SC 1.4.3][1]
    - &gt= 3:1 for large text: 18 pt (typically 24px) or larger [SC 1.4.3][1]
    - &gt= 3:1 for tab bar against page background [SC 1.4.11][2]
    - Focus State: if the focus ring has a radius of [SC 1.4.11][2]
        - &lt 3px: &gt= 4.5.1 between button &lt&gt focus &lt&gt background
        - &gt 3px: &gt= 3.1 button button &lt&gt focus &lt&gt background
    - `alt=""` for decorative icons [SC 1.1.1][3]

## States
-  Color contrast guidelines do not apply to disabled tabs

## Interaction Design
- **Define Manual vs. Automatic:** Designers **MUST** specify which interaction model they want in specs for engineering. By default, Splunk Design System uses manual tabs and supports automatic tabs. 
    - **Automatic activation:** When a user focuses on a tab, it automatically loads. This is recommended for static text and some images.
    - **Manual activation:** A user must click the tab or use <kbd>Enter/Space</kbd> to load the content in tabs. This is recommended for dynamic content such as tables, visualizations, etc.
- Focus state does **SHOULD NOT** cover visual design elements that illustate which tab a user is on, or that the elements are not the same color as the selected bar.
- **MUST** have keyboard navigation [SC 2.1][4]:
    - <kbd>Tab</kbd> and <kbd>Shift+Tab</kbd> to move into the tablist, focusing on active tab 

        - A second <kbd>Tab</kbd> and <kbd>Shift+Tab</kbd> moves to the next interactive element in the sequence
    - If the design has a tablist that runs..
        - Horizontally: <kbd>Left</kbd> and <kbd>Right Arrow</kbd> to circle thru tabs
        - Vertically: <kbd>Up</kbd> and <kbd>Down Arrow</kbd> to circle thru tabs
    - disabled tabs **MUST** be skipped in navigation 

## Implementation
- Tabs **MUST** be implemented as a list so users receive correct information
- As a fallback mechanism, this allows tabs to gracefully degrade back to a list of content
- Tabs as part of a navigation bar **MUST** be implemented as links and use manual navigation
- If tabs use quantifier, this number **MUST** to be announced by screen reader
- Vertical tab bars **MUST** have `aria-orientation=vertical`
- Observe specifications for manual or automatic activation as prescribed by the interaction model section

[1]: https://www.w3.org/TR/WCAG21/#contrast-minimum
[2]: https://www.w3.org/TR/WCAG21/#non-text-contrast
[3]: https://www.w3.org/TR/WCAG21/#non-text-content
[4]: https://www.w3.org/TR/WCAG21/#keyboard-accessible


